from flask import Blueprint, redirect, session, flash, request, render_template

from book_shujuku import *
import math

blue_print = Blueprint ("blue_print", __name__)


# ===============================================初始化数据表=============================================================

@blue_print.route ("/init")
def init ():
    db.create_all ()  # 初始化创建所有数据表
    flash ("已成功向数据库中添加数据表，正在初始化管理员用户名及密码。。。。。。")
    return redirect ("/admin")  # 创建成功后重定向到初始化管理员用户名和密码页面


# ===============================================初始化管理员用户名及密码===================================================
@blue_print.route ("/admin")
def admin ():
    admin_name = Admin.query.all ()  # 获取管理员信息表中的所有管理员信息
    if admin_name == []:  # 判断获取的信息是否时空的，如果空，则徐重新初始化管理员信息
        username_password = Admin (username = "田玉亭", password = "xiaojian")  # 写入管理员信息
        db.session.add (username_password)  # 向管理员信息表中写入管理员信息
        db.session.commit ()  # 提交
        flash ("管理员用户名及密码已初始化完成，请登录。。。。。。")  # 闪现提示初始化成功，可以登录使用
        return redirect ("/login")  # 重定向到登录页面
    flash ("管理员用户名及密码已存在，可直接登录系统。。。。。。")  # 如果不为空，则提示管理员信息已存在，可以直接登录是使用
    return redirect ("/login")  # 重定向到登录页面


# =================================================登录页面==============================================================
token = ""  # 创建全局变量为空值


@blue_print.route ("/login", methods = ["GET", "POST"])
def login ():
    global token  # 声明修改全局变量
    if request.method == "POST":  # 如果请求方式时POST，则继续下面操作
        username = request.form.get ("username")  # 获取表当中name为username的数据
        password = request.form.get ("password")  # 获取表单中nanme为password的数据
        admin_name = Admin.query.first ()  # 获取数据库中一条数据
        if admin_name.username == username and admin_name.password == password:  # 判断如果获取两项数据与数据库中数据是否一致
            session ["username"] = username  # 将获取的username写入到session中
            token = "123456"  # 给全局变量token赋值
            flash (("恭喜管理员%s，登录成功。。。。。。") % username)  # 如果一致，则闪现提示登录成功，
            return redirect ("/index")  # 重定向到首页
        flash ("管理员用户或者密码错误，请重新输入。。。。。。")  # 如果获取数据与数据表中数据不一致，则闪现提示用户名或密码错误，请重新登录
        return render_template ("login.html")  # 重定向到登录页面
    return render_template ("login.html")  # 如果请求方式是GET时进入登录页面


# ===============================================登录成功后进入首页========================================================
@blue_print.route ("/index")
def index ():
    if token:  # 判断token是否存在
        username = session.get ("username")  # token存在则获取存入session中的用户名
        return render_template ("index.html", username = username)  # 重定向到首页，并将获取的用户名写入到首页中
    else:  # 如果token不存在
        flash ("请先登录")  # 闪现提示先登录
        return redirect ("/login")  # 重定向到登录页面


# ===============================================自定义方式--分类表分页显示===================================================

@blue_print.route ("/pagelist")
def pagelist ():
    page_num = request.args.get ("page_num", 1)  # 进入分类分页显示页面，默认进入第一页
    page_num = int (page_num)  # 将页面转成整形类型
    per_page = 3  # 设置每页显示3条数据
    total = Cate.query.count ()  # 获取数据表中所有条数
    pages = math.ceil (total / per_page)  # 用所有条数除以每页显示的3条得出可以分几页，用math.ceil()方法转换成整形
    pagination = Cate.query.paginate (page_num, per_page)  # 分类表获取paginate方法，将页面数及条数当成参数传入
    if page_num <= 1:  # 判断当前页面是否小于等于第一页
        prev_num = 1  # 是就赋值成第一页
    else:  # 否则
        prev_num = page_num - 1  # 跳转到上一页
    if page_num >= pages:  # 判断是否大于或者等于最后一页
        next_num = pages  # 如果是，就赋值最后一页
    else:  # 否则
        next_num = page_num + 1  # 如果不是，就进入下一页

    return render_template ("catelist.html", page = pagination, prev_num = prev_num, next_num = next_num,
                            page_num = page_num, per_page = per_page)
    # 判断过之后进入分类列表页面，将paginate方法，上一页，下一页传入到网页中


# ===============================================排序分类页面=============================================================

@blue_print.route ("order")
def order ():
    cates = Cate.query.order_by ((Cate.id).desc ()).all ()
    return render_template ("catelist.html", cates = cates)


# ===============================================添加分类页面=============================================================

@blue_print.route ("/add_cate", methods = ["GET", "POST"])  # 此路由进入添加分类页面，请求方式为GET及POST
def add_cate ():
    if request.method == "POST":  # 如果请求方式为POST
        name = request.form.get ("name")  # 从表单中获取添加的分类名
        if Cate.query.filter (Cate.name == name).first ():  # 判断此分类是否存在
            flash ("该分类已存在，请重新添加")  # 如果存在，闪现提示
            return redirect ("/add_cate")  # 重定向到添加页面
        ret = Cate (name = request.form.get ("name"))  # 否则，给类数据表中的name进行赋值
        db.session.add (ret)  # 将赋值过之后的类名添加到数据表中
        db.session.commit ()  # 提交添加请求
        flash ("添加成功")  # 闪现提示添加成功
        return redirect ("/pagelist")  # 重定向到分页显示类列表首页
    return render_template ("add_cate.html")  # 如果请求方式为GET，则进入添加分类页面


# =================================================修改分类表数据页面======================================================

@blue_print.route ("/updatecate/<int:id>", methods = ["GET", "POST"])  # 设置删除路由，请求方式为GET,POST
def update (id):  # 传入参数id
    ret = Cate.query.get (id)  # 获取数据表中的数据，get方式是只获取主键
    if request.method == "GET":  # 如果请求方式为GET
        name = ret.name  # 获取数据库中的nae
        return render_template ("update_cate.html", name = name)  # 将数据库中的数据放入输入框中，这样就可以看到修改之前的数据

    if request.method == "POST":  # 如果请求方式为POST
        update_name = request.form.get ("name")  # 获取输入表单中的name
        ret.name = update_name  # 给数据表中的name重新赋值成为获取表单中的数据
        db.session.commit ()  # 提交修改请求
        flash ("修改成功，请继续您的其它操作。。。。。。")  # 闪现提示修改成功
        return redirect ("/pagelist")  # 修改成功后重定向到分页显示列表页面


# =================================================删除分类表数据页面======================================================

@blue_print.route ("/deletecate/<int:id>")  # 设置路由为删除页面
def del_cate (id):  # 传入参数id
    ret = Cate.query.get (id)  # 获取数据表中的id，get方式是只获取主键
    db.session.delete (ret)  # 使用delete方法删除获取到的id
    db.session.commit ()  # 提交删除请求
    flash ("删除成功，请继续您的其它操作。。。。。。")  # 闪现提示删除成功
    return redirect ("/pagelist")  # 删除成功后重定向到分页显示分类列表页面


# =================================================系统方式--分页显示图书列表===============================================


@blue_print.route ("/goodslist")
def goodslist ():
    page_num = int (request.args.get ("page_num", 1))  # 点击进去之后进入分页显示页面，且默认显示第一页
    per_page = 3  # 设置每页显示三条数据
    ttl = Book.query.count ()  # 获取数据库中一共有多少条数据
    ttl_page = math.ceil (ttl / per_page)  # 用总条数除以每页显示数=一共有多少页，将小数转换成整数，且+1，这样就可以在点击下一页时不会报错
    pagination = Book.query.paginate (page_num, per_page)  # paginates是一个方法，将页数以及每页显示数当成参数放入
    cate = Cate.query.all ()
    if page_num <= 1:  # 如果当前页面在第一页或者小于第一页
        per_num = 1  # 那么点击之后跳转到第一页
    else:
        per_num = page_num - 1  # 否则跳转到上一页
    if page_num >= ttl_page:  # 如果当前页面是最后一页，或者小于最后一页
        next_num = ttl_page  # 那么点击之后跳转到最后一页
    else:
        next_num = page_num + 1  # 否则跳转到下一页
    return render_template ("goodslist.html", pagination = pagination, per_num = per_num, next_num = next_num,
                            cate = cate, page_num = page_num, per_page = per_page)


# ===================================================添加图书页面=========================================================
@blue_print.route ("/add_goods", methods = ["GET", "POST"])  # 设置路由为添加图书页面，请求方式为GET,POST
def add_goods ():
    if request.method == "GET":  # 请求方式为GET时，进入输入添加页面，
        cates = Cate.query.all ()  # 获取分类表中的数据，作为参数传入网页中，以便添加外键分类时使用
        return render_template ("add_goods.html", cates = cates)  # 进入添加图书页面
    else:
        name = request.form.get ("name")  # 获取网页表单中输入框name为name的数据
        author = request.form.get ("author")  # 获取网页表单中输入框namne为author的数据
        cate_id = request.form.get ("cate_id")  # 获取网页表单中下拉框namne为cate_id的数据
        goods = Book (name = name, author = author, cate_id = cate_id)  # 将获取到的数据赋值给图书表中对应的字段
        db.session.add (goods)  # 将赋值后的数据添加到图书表中
        db.session.commit ()  # 提交添加请求
        flash ("成功添加图书，请继续您的操作。。。。。。")  # 闪现提示添加成功
        return redirect ("/goodslist")  # 添加成功后重定向到分页显示图书列表页面


# ====================================================修改图书===========================================================

@blue_print.route ("/updatebook/<int:id>", methods = ["GET", "POST"])  # 设置删除路由，请求方式为GET,POST
def updatebook (id):  # 传入参数id
    ret = Book.query.get (id)  # 获取数据表中的数据，get方式是只获取主键
    if request.method == "GET":  # 如果请求方式为GET
        cates = Cate.query.all ()
        name = ret.name  # 获取数据库中的name
        author = ret.author  # 获取数据表中的author
        cate_id = ret.cate_id  # 获取数据表中的分类id
        print (name, author, cate_id)
        return render_template ("update_book.html", name = name, author = author, cate_id = cate_id,
                                cates = cates)  # 将数据库中的数据放入输入框中，这样就可以看到修改之前的数据

    if request.method == "POST":  # 如果请求方式为POST
        update_name = request.form.get ("name")  # 获取输入表单中的name
        update_author = request.form.get ("author")  # 获取输入表单中的id
        update_cate_id = request.form.get ("cate_id")  # 获取输入表单中的id
        print (update_name, update_author, update_cate_id)
        ret.name = update_name  # 给数据表中的id重新赋值成为获取表单中的数据
        ret.author = update_author  # 给数据表中的name重新赋值成为获取表单中的数据
        ret.cate_id = update_cate_id  # 给数据表中的name重新赋值成为获取表单中的数据
        print (ret.name, ret.author, ret.cate_id)
        db.session.commit ()  # 提交修改请求
        flash ("图书信息修改成功，请继续您的其它操作。。。。。。")  # 闪现提示修改成功
        return redirect ("/goodslist")  # 修改成功后重定向到分页显示列表页面


# ====================================================删除图书===========================================================

@blue_print.route ("/deletebook/<int:id>")  # 设置路由为删除页面
def del_book (id):  # 传入参数id
    ret = Book.query.get (id)  # 获取数据表中的id，get方式是只获取主键
    db.session.delete (ret)  # 使用delete方法删除获取到的id
    db.session.commit ()  # 提交删除请求
    flash ("成功删除图书，请继续您的其它操作。。。。。。")  # 闪现提示删除成功
    return redirect ("/goodslist")  # 删除成功后重定向到分页显示分类列表页面
